#include "StartView.hpp"

using namespace BFT::order::messages;

StartView::StartView(uint32_t _view, uint32_t _seq, boost::shared_ptr<BFT::messages::HistoryDigest> _history, uint32_t _sendingReplica)
	: BFT::messages::MacMessage(START_VIEW, computeSize(), _sendingReplica)

{
	viewNo = _view;
	seqNo = _seq;
	history = _history;
	
	int offset = getOffset();
	int bytes_size;
	boost::shared_ptr<char> bytes = getBytes(bytes_size);
	
	//write down the view number
	*(uint32_t*)(bytes.get()+offset) = htonl(viewNo);
	offset += VIEW_NUMBER_SIZE;
	
	//write down the sequence number
	*(uint32_t*)(bytes.get()+offset) = htonl(seqNo);
	offset += SEQUENCE_NUMBER_SIZE;	
	
	//write down the history digest
	boost::shared_ptr<char> history_bytes = history.get()->getBytes();
	memcpy( (void*)(bytes.get()+offset) , (const void*)(history_bytes.get()) , DIGEST_SIZE );
	offset += DIGEST_SIZE;
}

StartView::StartView(boost::shared_ptr<char> _bytes, int _bytes_size)
	: BFT::messages::MacMessage(_bytes, _bytes_size)
{
	if (getTag() != START_VIEW)
	{
		fprintf(stderr,"Trying tro build a start view from bytes with different tag\n");
		exit(181);
	}
	
	int offset = getOffset();
	
	//read the view number
	viewNo = ntohl( *(uint32_t*)(_bytes.get()+offset) );
	offset += VIEW_NUMBER_SIZE;
	
	//read the sequence number
	seqNo = ntohl( *(uint32_t*)(_bytes.get()+offset) );
	offset += SEQUENCE_NUMBER_SIZE;
	
	//read the history
	boost::shared_ptr<char> history_bytes ( (char*)malloc(DIGEST_SIZE), free );
	memcpy( (void*)(history_bytes.get()), (const void*)(_bytes.get()+offset) , DIGEST_SIZE);
	offset += DIGEST_SIZE;
	history = BFT::messages::HistoryDigest::fromBytes(history_bytes, DIGEST_SIZE);
	
	if( (unsigned int)offset != _bytes_size - getAuthenticationSize())
	{
		fprintf(stderr,"trying to build a start view from invalid bytes\n");
		exit(182);
	}
}

uint32_t StartView::computeSize()
{
	return VIEW_NUMBER_SIZE + 
	       SEQUENCE_NUMBER_SIZE +
	       DIGEST_SIZE;
}
